import requests
import json
import sys
import os
from datetime import datetime

def load_config(config_file='config.json'):
    """Load configuration from JSON file"""
    try:
        with open(config_file, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"Configuration file {config_file} not found!")
        sys.exit(1)
    except json.JSONDecodeError:
        print(f"Invalid JSON in configuration file {config_file}!")
        sys.exit(1)

def get_environment_config(config, env_name):
    """Get configuration for specified environment"""
    if env_name not in config:
        print(f"Environment '{env_name}' not found in configuration!")
        print(f"Available environments: {list(config.keys())}")
        sys.exit(1)
    return config[env_name]

class GitLabCommitDetails:
    def __init__(self, base_url, token):
        self.base_url = base_url
        self.headers = {'PRIVATE-TOKEN': token}
        self.session = requests.Session()
        self.session.headers.update(self.headers)
    
    def get_commit_with_stats(self, project_id, commit_sha):
        """Get detailed commit information including file changes and statistics"""
        commit_url = f'{self.base_url}/projects/{project_id}/repository/commits/{commit_sha}'
        
        try:
            response = self.session.get(commit_url, timeout=10)
            if response.status_code == 200:
                return response.json()
            else:
                print(f"Failed to get commit details: {response.status_code}")
                print(response.text)
                return None
        except Exception as e:
            print(f"Error getting commit details: {e}")
            return None
    
    def get_commit_diff(self, project_id, commit_sha):
        """Get the diff/changes for a specific commit"""
        diff_url = f'{self.base_url}/projects/{project_id}/repository/commits/{commit_sha}/diff'
        
        try:
            response = self.session.get(diff_url, timeout=10)
            if response.status_code == 200:
                return response.json()
            else:
                print(f"Failed to get commit diff: {response.status_code}")
                return None
        except Exception as e:
            print(f"Error getting commit diff: {e}")
            return None
    
    def analyze_commit(self, project_id, commit_sha):
        """Get comprehensive commit analysis"""
        print(f"Analyzing commit {commit_sha[:8]}...")
        
        # Get commit details with stats
        commit_details = self.get_commit_with_stats(project_id, commit_sha)
        if not commit_details:
            return None
        
        # Get commit diff
        commit_diff = self.get_commit_diff(project_id, commit_sha)
        
        return {
            'commit_info': commit_details,
            'diff_info': commit_diff
        }
    
    def display_commit_analysis(self, analysis):
        """Display detailed commit analysis"""
        if not analysis:
            print("No analysis data available.")
            return
        
        commit = analysis['commit_info']
        diff = analysis['diff_info']
        
        print(f"\n{'='*80}")
        print(f"DETAILED COMMIT ANALYSIS")
        print(f"{'='*80}")
        
        # Basic commit info
        print(f"Commit ID: {commit['id']}")
        print(f"Short ID: {commit['short_id']}")
        print(f"Title: {commit['title']}")
        print(f"Message: {commit['message']}")
        print(f"Author: {commit['author_name']} <{commit['author_email']}>")
        print(f"Date: {commit['authored_date']}")
        print(f"Web URL: {commit['web_url']}")
        
        # Statistics
        if 'stats' in commit:
            stats = commit['stats']
            print(f"\nCODE STATISTICS:")
            print(f"  Additions: +{stats.get('additions', 0)} lines")
            print(f"  Deletions: -{stats.get('deletions', 0)} lines")
            print(f"  Total changes: {stats.get('total', 0)} lines")
        
        # File changes
        if diff:
            print(f"\nFILE CHANGES ({len(diff)} files modified):")
            for i, file_diff in enumerate(diff, 1):
                print(f"\n{i}. {file_diff.get('new_path', file_diff.get('old_path', 'Unknown'))}")
                print(f"   Status: {file_diff.get('new_file', False) and 'New file' or file_diff.get('deleted_file', False) and 'Deleted' or 'Modified'}")
                print(f"   Changes: +{file_diff.get('additions', 0)} -{file_diff.get('deletions', 0)}")
                
                # Show a preview of the diff (first few lines)
                if 'diff' in file_diff and file_diff['diff']:
                    diff_lines = file_diff['diff'].split('\n')[:10]  # First 10 lines
                    print(f"   Preview:")
                    for line in diff_lines:
                        if line.startswith('+++') or line.startswith('---'):
                            continue
                        print(f"     {line}")
                    if len(file_diff['diff'].split('\n')) > 10:
                        print(f"     ... (truncated, total {len(file_diff['diff'].split('\n'))} lines)")
        
        print(f"\n{'='*80}")

def main():
    if len(sys.argv) < 4:
        print("Usage: python get_commit_details.py <environment> <project_id> <commit_sha>")
        print("\nExample:")
        print("  python get_commit_details.py local 566 5abc133df959caf34468cda16349a4326d98955a")
        print("  python get_commit_details.py local 566 5abc133d")
        sys.exit(1)
    
    env_name = sys.argv[1]
    project_id = int(sys.argv[2])
    commit_sha = sys.argv[3]
    
    # Get script directory to find config file
    script_dir = os.path.dirname(os.path.abspath(__file__))
    config_file = os.path.join(script_dir, 'config.json')
    
    # Load configuration
    config = load_config(config_file)
    env_config = get_environment_config(config, env_name)
    base_url = env_config['url']
    token = env_config['token']
    
    print(f"GitLab Commit Details Analyzer")
    print(f"Environment: {env_name}")
    print(f"API URL: {base_url}")
    print(f"Project ID: {project_id}")
    print(f"Commit: {commit_sha}")
    print()
    
    try:
        # Initialize analyzer
        analyzer = GitLabCommitDetails(base_url, token)
        
        # Analyze commit
        analysis = analyzer.analyze_commit(project_id, commit_sha)
        
        # Display results
        analyzer.display_commit_analysis(analysis)
        
        # Save detailed analysis if requested
        if '--save' in sys.argv:
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"commit_analysis_{commit_sha[:8]}_{timestamp}.json"
            
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    json.dump(analysis, f, indent=2, ensure_ascii=False)
                print(f"\nDetailed analysis saved to: {filename}")
            except Exception as e:
                print(f"Failed to save analysis: {e}")
        
    except KeyboardInterrupt:
        print("\nOperation cancelled by user.")
        sys.exit(1)
    except Exception as e:
        print(f"Error occurred: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()
